package com.liveinstars.im.handler;

import com.liveinstars.im.entity.Msg;
import com.liveinstars.im.core.Session;
import com.liveinstars.im.core.SessionManager;
import com.liveinstars.im.corebean.MsgHelper;
import com.liveinstars.im.corebean.PingMessage;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.InetSocketAddress;

/**
 * @author ting
 */
@ChannelHandler.Sharable
@Service
public class ServerClientHandler extends SimpleChannelInboundHandler<PingMessage> {

	@Value("${netty.server.id}")
	public Long chatServerId;

	@Value("${netty.server.ip}")
	public String ip;

	@Value("${netty.server.outip}")
	public String outIp;

	@Value("${netty.server.port}")
	public Integer port;

	@Value("${netty.server.name}")
	public String chatServerName;

	private static final Logger LOGGER = LoggerFactory.getLogger(ServerClientHandler.class);

	/**
	 * 当出现WRITER_IDLE、ALL_IDLE时则需要向客户端发出ping消息，试探远端是否还在
	 */
	private void sendPing(ChannelHandlerContext ctx) {
		Session session = SessionManager.get(ctx.channel().id().toString());
		if (session != null) {

			Msg.Message ping = MsgHelper.newPingMessage(
					Msg.MessageType.SERVER_PING, ip + ":"
							+ port);
			session.send(ping);
			ctx.fireChannelRead(ping);
		}

	}

	/**
	 * 利用写空闲发送心跳检测消息
	 * @param ctx
	 * @param evt
	 * @throws Exception
	 */
	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
			throws Exception {
		if (evt instanceof IdleStateEvent) {
			IdleStateEvent e = (IdleStateEvent) evt;
			switch (e.state()) {
			case WRITER_IDLE:
				LOGGER.info("ServerClientHandler WRITER_IDLE");
				sendPing(ctx);
				LOGGER.info("ServerClientHandler send ping to server。");
				break;
			default:
				break;
			}
		}
	}

	@Override
	protected void channelRead0(ChannelHandlerContext channelHandlerContext,
			PingMessage baseMsg) throws Exception {

		InetSocketAddress insocket = (InetSocketAddress) channelHandlerContext
				.channel().remoteAddress();
		String ip = insocket.getAddress().getHostAddress();
		int port = insocket.getPort();
		LOGGER.info("ServerClientHandler receive ping from server port:" + port);
		LOGGER.info("msgType:" + baseMsg.getMessageType());
		System.out.println("msgType:" + baseMsg.getMessageType());
		ReferenceCountUtil.release(baseMsg);
	}
}